package cn.bigfire.wzdj.util;

import cn.bigfire.wzdj.frame.WZDJMainFrame;
import cn.bigfire.wzdj.pojo.datao.LocalDO;
import cn.bigfire.wzdj.pojo.httpVo.UserInfo;
import cn.bigfire.wzdj.pojo.httpVo.WZDJLocalItem;
import cn.bigfire.wzdj.pojo.srcVo.Wzdj;
import cn.bigfire.wzdj.pojo.vo.DHWzdjCfg;
import cn.bigfire.wzdj.pojo.vo.Goods;
import cn.bigfire.wzdj.pojo.vo.GoodsVO;
import cn.bigfire.wzdj.pojo.vo.RelicCfg;
import cn.bigfire.wzdj.service.WZDJService;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.resource.ResourceUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.Channel;
import io.netty.util.internal.ThrowableUtil;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

@Data
public class Stores {

    public static int version = 1;

    private static final Logger log = LoggerFactory.getLogger(Stores.class);
    //login cache
    public static File localFile = FileUtil.file(Constant.DATA_DIR + "wzdj_local.json");
    public static LocalDO localDO = new LocalDO();

    //config
    public static JSONObject goodsCfg = new JSONObject();//商店配置信息
    public static HashMap<String, RelicCfg> relicCfgMap = new HashMap<>();//圣物配置信息
//    public static List<String> dhCodeList = new ArrayList<>();//可用的兑换码
    public static HashMap<Integer,Integer> lvMaxExpMap = new HashMap<>();//等级配置信息

    public DHWzdjCfg dhWzdjCfg = new DHWzdjCfg();

    static {
        try {
            String shopJsonStr = ResourceUtil.readUtf8Str("json/shopGoods.json");
            String relicJsonStr = ResourceUtil.readUtf8Str("json/relicCfg.json");

            //加载商店配置文件
            goodsCfg = JSON.parseObject(shopJsonStr);
            //加载 圣物配置
            JSONObject relicJsonObject  = JSON.parseObject(relicJsonStr);
            relicJsonObject.forEach((key, val) -> relicCfgMap.put(key, JSON.parseObject(val.toString(), RelicCfg.class)));
            lvMaxExpMap.put(1, 300);
            lvMaxExpMap.put(2, 800);
            lvMaxExpMap.put(3, 1100);
            lvMaxExpMap.put(4, 1600);
            lvMaxExpMap.put(5, 2400);
            lvMaxExpMap.put(6, 3500);
            lvMaxExpMap.put(7, 5300);
            lvMaxExpMap.put(8, 7900);
            lvMaxExpMap.put(9, 11800);
            lvMaxExpMap.put(10, 17700);
            lvMaxExpMap.put(11, 26700);
            lvMaxExpMap.put(12, 40000);
            lvMaxExpMap.put(13, 60200);
            lvMaxExpMap.put(14, 90500);
            lvMaxExpMap.put(15, 136000);
            lvMaxExpMap.put(16, 203000);
            lvMaxExpMap.put(17, 304000);
            lvMaxExpMap.put(18, 457000);
            lvMaxExpMap.put(19, 685000);
            lvMaxExpMap.put(20, 1030000);
            lvMaxExpMap.put(21, 1540000);
            lvMaxExpMap.put(22, 2310000);
            lvMaxExpMap.put(23, 3470000);
            lvMaxExpMap.put(24, 5200000);
            lvMaxExpMap.put(25, 0);
            //满级25级
        } catch (Exception e) {
            String errStr = ThrowableUtil.stackTraceToString(e);
            log.error(errStr);
            WZDJMainFrame.consoleTextArea.append(errStr + "\n");
        } catch (Throwable throwable) {
            String errStr = ThrowableUtil.stackTraceToString(throwable);
            log.error(errStr);
            WZDJMainFrame.consoleTextArea.append(errStr + "\n");
        }
    }

/*
    体力计算  恢复，广告，钻石买体力，升级奖励，活动奖励

    恢复：10分钟恢复一点体力 一小时恢复6点体力 24小时恢复     144点体力
    广告：3次广告                                        15点体力
    钻石买体力：50|70|100|125|150|(10个)200|             225点体力
    升级奖励：(升级奖励15体力)
    活动奖励：(不固定)

    一天总体力数: 225+114=369
    一天封顶可玩: 369/5=73局游戏


    消耗
    一局差不多9-22分钟之间
    求平均按15分钟一局   1小时4局  24*4=96局
    保守10分钟一局       1小时6局  24*6=144局
    所以说体力还是不够用的。
*/



    public static Goods getCfgGoods(String shopId, String goodsId) {
        try {
            //获取商品
            JSONObject shopInfo = goodsCfg.getJSONObject(shopId + "");
            if (shopInfo != null && shopInfo.containsKey("goods")) {
                JSONObject goodsObject = shopInfo.getJSONObject("goods");
                if (goodsObject != null && goodsObject.containsKey(goodsId)) {
                    return goodsObject.getObject(goodsId, Goods.class);
                }
            }
        } catch (Exception e) {
//            System.err.printf(" has err:" + e.getMessage());
        }
        return new Goods();
    }

//    public static Goods getCfgGoods(String shopId, String goodsId) {
//
//    }

    public static Goods getCfgGoods(int shopId, int goodsId) {
        return getCfgGoods(shopId + "", goodsId + "");
    }

    public static HashSet<String> keepFighter = new HashSet<>();
    static {
        //财神
        keepFighter.add(Consts.Fighter.F3005.getId());
        keepFighter.add(Consts.Fighter.F3003.getId());
        keepFighter.add(Consts.Fighter.F2001.getId());
        //猫
        keepFighter.add(Consts.Fighter.F3001.getId());
        keepFighter.add(Consts.Fighter.F1001.getId());
        keepFighter.add(Consts.Fighter.F1004.getId());
        //无极大师
//        keepFighter.add(Consts.Fighter.F4003.getId());
        keepFighter.add(Consts.Fighter.F3004.getId());
        keepFighter.add(Consts.Fighter.F2004.getId());
        //孙悟空
        keepFighter.add(Consts.Fighter.F4001.getId());
        keepFighter.add(Consts.Fighter.F3003.getId());
        keepFighter.add(Consts.Fighter.F1002.getId());
        //卡皮巴拉 F5027
        keepFighter.add(Consts.Fighter.F3002.getId());
        keepFighter.add(Consts.Fighter.F3004.getId());
        keepFighter.add(Consts.Fighter.F2003.getId());
    }

    @Getter
    private static Stores instance = new Stores();
    @Getter
    @Setter
    private static WZDJMainFrame wzdjMainFrame;

    volatile String qrUuid = "";
    volatile boolean isQrExpired = true;

    //http wx用户信息token相关

    String account;
    String password;//密码|wx code
    String loginType;

    String selectItemStr;
    WZDJLocalItem wzdjLocalItem = new WZDJLocalItem();
    UserInfo userInfo;
    AtomicInteger energy = new AtomicInteger(0);
    AtomicInteger energyNext = new AtomicInteger(10 * 60);//10分钟
    AtomicInteger model = new AtomicInteger(0);
    AtomicBoolean isFight = new AtomicBoolean(false);
    int battleType = 0;//0大厅 1 普通 2 困难 3未知 4竞技 5 地狱

    //商店信息
    AtomicInteger freshCnt = new AtomicInteger(0);
    HashMap<Integer, GoodsVO> goodsVOMap = new HashMap<>();//<下标,商品信息> 下标0-5每日刷新商品   5 买体力商品
    HashMap<Integer, Wzdj.ShopInfo> shopMap = new HashMap<>();//存商店信息


    // home缓存
    Channel homeChannel;

    //ws WZDJ用户信息 用户基本信息 uid,名称，等级，经验等
    boolean isLogin = false;
    Wzdj.BasicInfo basicInfo;
    ConcurrentHashMap<String, Long> itemMap = new ConcurrentHashMap<>();

    //我的邀请码
    String  myInviteCode = "";
    //添加好友 申请列表
    List<Wzdj.FriendInfo> beApplyList = new ArrayList<>();
    //好友列表
    List<Wzdj.FriendInfo> myFriendList = new ArrayList<>();
    //PVP

    AtomicInteger dayPass1 = new AtomicInteger(0);//每日普通 80是否通过
    AtomicInteger dayPass2 = new AtomicInteger(0);//每日困难 80是否通过
    AtomicInteger dayPass5 = new AtomicInteger(0);//每日地狱 80是否通过

    AtomicInteger dayPvpWin = new AtomicInteger(0);//0-2为次数
    AtomicInteger dayPvpNeed= new AtomicInteger(0);//2为次数
    AtomicInteger dayPvpReward = new AtomicInteger(0);//pvp奖励领取状态

    AtomicInteger pass1Max = new AtomicInteger(0);//本期普通 最大打到哪一关
    AtomicInteger pass2Max = new AtomicInteger(0);//本期困难 最大打到哪一关
    AtomicInteger pass5Max = new AtomicInteger(0);//本期地狱 最大打到哪一关


    public void dayChange() {
        dayPass1.set(0);
        dayPass2.set(0);
        dayPass5.set(0);

        dayPvpWin.set(0);
        dayPvpReward.set(0);
    }

    //room 缓存
    String roomNum = "1234";//用于取消创建的房间号
    int roomNumType = 1;

    //fight
    Channel fightChannel;
    Wzdj.RpcClientFightMatchSuccess rpcClientFightMatchSuccess;
    volatile int wave = 0;//当前管卡
    AtomicInteger waveTime = new AtomicInteger(0);//当前管卡时间
    volatile int monsterLimit = 0;//当前怪物上限
    volatile int monsterNum = 0;//当前怪物

    //我的信息
    volatile int myFood = 0;//当前金币数
    volatile int myLuckCoin = 0;//当前幸运币
    volatile int myPopuNum = 0;//当前战斗机数量
    volatile int myPopuLimit = 0;//当前战斗机上限

    volatile int myUid = 0;
    volatile int mySide = 0;
    List<Wzdj.FightFighterData> myFight5List = new ArrayList<>();
    Wzdj.FightPlayerData myFightPlayerData = new Wzdj.FightPlayerData();//快照信息
    ConcurrentHashMap<String, CopyOnWriteArrayList<Wzdj.FightActorData>> myActorMap = new ConcurrentHashMap<>();
    ConcurrentHashMap<Integer, CopyOnWriteArrayList<Wzdj.FightActorData>> myGridMap = new ConcurrentHashMap<>();
    volatile int callCost = 20;


    //强化等级
    AtomicInteger enhance1 = new AtomicInteger(1);
    AtomicInteger enhance2 = new AtomicInteger(1);
    AtomicInteger enhance3 = new AtomicInteger(1);
    AtomicInteger enhance4 = new AtomicInteger(1);

    //对方信息
    volatile int itFood = 0;//当前金币数
    volatile int itLuckCoin = 0;//当前幸运币
    volatile int itPopuNum = 0;//当前战斗机数量
    volatile int itPopuLimit = 0;//当前战斗机上限

    volatile int itUid = 0;
    volatile int itSide = 0;
    Wzdj.BasicInfo itBasicInfo;
    List<Wzdj.FightFighterData> itFight5List = new ArrayList<>();
    Wzdj.FightPlayerData itFightPlayerData = new Wzdj.FightPlayerData();//快照信息
    ConcurrentHashMap<String, CopyOnWriteArrayList<Wzdj.FightActorData>> itActorMap = new ConcurrentHashMap<>();
    ConcurrentHashMap<Integer, CopyOnWriteArrayList<Wzdj.FightActorData>> itGridMap = new ConcurrentHashMap<>();

    //辅助聊天
    volatile boolean homeAutoChat = false;
    volatile boolean fightReplayChat = true;
    volatile boolean fightWaveChat = false;
    //辅助功能
    volatile boolean autoCall = true;          //自动召唤
    volatile boolean autoCombination = true;   //自动3合1
    volatile boolean autoMythic = true;        //自动合成神话
    volatile boolean autoMove = true;          //自动移动
    volatile boolean autoRemove = true;       //自动删除
    volatile boolean autoGambling = true;      //自动赌博
    volatile boolean autoStrengthen = true;    //自动强化
    volatile boolean autoHunting = true;       //自动狩猎
    volatile boolean accelerate = false;       //加速

    volatile int lastFromGrid = -1;
    volatile int lastToGrid = -1;
    volatile int lastRemoveId = -1;



    public boolean isFightFull(){
        if (myPopuLimit > 20 && myPopuNum >= myPopuLimit) {
            return true;
        }
        for (int i = 0; i < 18; i++) {
            Stores.getInstance().getMyGridMap().putIfAbsent(i, new CopyOnWriteArrayList<>());
        }
        for (CopyOnWriteArrayList<Wzdj.FightActorData> list : Stores.getInstance().getMyGridMap().values()) {
            if (list.isEmpty()) {
                return false;
            }
        }
        return true;
    }

    public String getMyUBase(){
        Integer exp = basicInfo.getExp();
        Integer max = lvMaxExpMap.getOrDefault(basicInfo.getLv() + 1, 0);
        int percent = exp * 100 / max;
        String percentStr = percent + "%";
        String expStr = String.format("%s/%s(进度%s)", exp, max, percentStr);
        int vip = WZDJService.getVip(basicInfo);
        return String.format("id:%s|%s|vip:%s|等级%s|经验:%s", basicInfo.getUid(), basicInfo.getName(), vip, basicInfo.getLv(), expStr);
    }

    public String getStatus() {
        if (homeChannel == null || !homeChannel.isActive()) {
            return "未连接";
        }
        return isFight.get() ? "战斗中" + wave : "大厅中";
    }


}
